﻿using SHZY.Common.Core.Manager;
using SHZY.Common.Core.Security;
using SHZY.Common.Enum;
using SHZY.Common.Extension;
using SHZY.Common.Filter;
using SHZY.Common.Models;
using SHZY.Common.Security;
using SHZY.DependencyInjection;
using SHZY.DynamicApiController;
using SHZY.FriendlyException;
using SHZY.Systems.Entitys.Permission;
using SHZY.Systems.Entitys.System;
using SHZY.Systems.Interfaces.System;
using SHZY.Business.Entitys.Dto.QmsBusiDefecthandle;
using SHZY.Business.Entitys;
using SHZY.Business.Interfaces;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using SHZY.Business.Entitys.Dto.QmsBusiDefecthandleDetail;
using SHZY.Business.Entitys.Dto.defecthandle;
using SHZY.Business.Entitys.Dto.QmsBusiInspectionitemdefect;
using SHZY.WorkFlow.Entitys.Entity;
using SHZY.EventHandler;
using SHZY.WorkFlow.Entitys.Enum;
using SHZY.WorkFlow.Interfaces.Repository;
using SHZY.WorkFlow.Interfaces.Manager;
using System.Linq;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Senparc.Weixin.Work.AdvancedAPIs.OaDataOpen;
using SHZY.Business.Entitys.Dto.QmsBusiIpqcinspectionitemdefect;

namespace SHZY.Business;

/// <summary>
/// 业务实现：不合格品处理单.
/// </summary>
[ApiDescriptionSettings(Tag = "Business", Name = "Defecthandle", Order = 200)]
[Route("api/Business/[controller]")]
public class QmsBusiDefecthandleService : IQmsBusiDefecthandleService, IDynamicApiController, ITransient
{
    /// <summary>
    /// 服务基础仓储.
    /// </summary>
    private readonly ISqlSugarRepository<QmsBusiDefecthandleEntity> _repository;

    /// <summary>
    /// 数据接口服务.
    /// </summary>
    private readonly IDataInterfaceService _dataInterfaceService;

    /// <summary>
    /// 用户管理.
    /// </summary>
    private readonly IUserManager _userManager;

    private readonly ITenant _tenant;

    private readonly IFlowTaskRepository _flowTaskRepository;

    private readonly IFlowTaskManager _flowTaskManager;

    /// <summary>
    /// 初始化一个<see cref="QmsBusiDefecthandleService"/>类型的新实例.
    /// </summary>
    public QmsBusiDefecthandleService(
        ISqlSugarRepository<QmsBusiDefecthandleEntity> qmsBusiDefecthandleRepository,
        IDataInterfaceService dataInterfaceService,
        ISqlSugarClient context,
        IUserManager userManager,
        IFlowTaskRepository flowTaskRepository,
        IFlowTaskManager flowTaskManager)
    {
        _repository = qmsBusiDefecthandleRepository;
        _dataInterfaceService = dataInterfaceService;
        _userManager = userManager;
        _tenant = context.AsTenant();
        _flowTaskRepository = flowTaskRepository;
        _flowTaskManager = flowTaskManager;
    }

    #region GET

    /// <summary>
    /// 获取不合格处理表单列表列表.
    /// </summary>
    /// <param name="input">请求参数.</param>
    /// <returns></returns>
    [HttpGet("")]
    public async Task<dynamic> GetList([FromQuery] QmsBusiDefecthandleListQueryInput input)
    {
        var queryable = _repository.Context.Queryable<QmsBusiDefecthandleEntity, UserEntity, FlowTaskEntity>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id, JoinType.Left, a.Id == c.Id))
            .Where(a => a.DeleteMark == null)
            .WhereIF(!string.IsNullOrEmpty(input.code), a => a.Code.Contains(input.code))
            .WhereIF(!string.IsNullOrEmpty(input.inspectionLot), a => a.InspectionLot.Contains(input.inspectionLot))
            .WhereIF(!string.IsNullOrEmpty(input.batchNumber), a => a.BatchNumber.Contains(input.batchNumber))
            .WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.Code.Contains(input.keyword) || a.InspectionLot.Contains(input.keyword) || a.BatchNumber.Contains(input.keyword))
            .WhereIF(!string.IsNullOrEmpty(input.material), a => a.MaterialCode.Contains(input.material) || a.MaterialDes.Contains(input.material))
            .WhereIF(!string.IsNullOrEmpty(input.type), a => a.Type.Equals(input.type))
            .Select((a, b, c) => new QmsBusiDefecthandleListOutput
            {
                id = a.Id,
                type = a.Type,
                typeDesc = SqlFunc.Subqueryable<DictionaryDataEntity>().Where(dic => dic.EnCode.Equals(a.Type) && dic.DictionaryTypeId.Equals("448687444825473541")).Select(dic => dic.FullName),
                code = a.Code,
                inspectionLotId = a.InspectionLotId,
                inspectionLot = a.InspectionLot,
                batchNumber = a.BatchNumber,
                materialCode = a.MaterialCode,
                materialDes = a.MaterialDes,
                supplier = a.Supplier,
                supplierDes = a.SupplierDes,
                orderNo = a.OrderNo,
                productionQty = a.ProductionQty,
                incomingQty = a.IncomingQty,
                status = string.IsNullOrEmpty(c.Status.ToString()) ? a.Status : c.Status,
                creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account),
                creatorUserId = a.CreatorUserId,
                createTime = a.CreatorTime,
                problem = a.Problem,
                decision = a.Decision,
                decisionName = a.DecisionName
            }).MergeTable();
            //.OrderByIF(string.IsNullOrEmpty(input.sidx), a => a.Id);
        if (!string.IsNullOrEmpty(input.sidx))
        {
            queryable.OrderBy(input.sidx + " " + input.sort);
        }
        else
        {
            queryable.OrderBy(it => it.id);
        }

        var data = await queryable.ToPagedListAsync(input.currentPage, input.pageSize);

        await _repository.Context.ThenMapperAsync(data.list, async item =>
        {
            // 问题原因
            var problemData = "[{\"id\":\"1\",\"fullName\":\"供应商问题\"},{\"id\":\"2\",\"fullName\":\"非供应商问题\"}]".ToObject<List<StaticDataModel>>();
            item.problem = string.IsNullOrEmpty(item.problem)? "": problemData.Find(it => item.problem.Equals(it.id)).fullName;

        });

        return PageResult<QmsBusiDefecthandleListOutput>.SqlSugarPageResult(data);
    }

    /// <summary>
    /// 获取不合格品处理单信息.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<dynamic> GetInfo(string id)
    {
        var data = (await _repository.FirstOrDefaultAsync(x => x.Id == id && x.DeleteMark == null)).Adapt<DefecthandleInfoOutput>();

        data.DetailList = (await _repository.Context.Queryable<QmsBusiDefecthandledetailEntity>().Where(x => x.DefectHandleCode == data.Code).ToListAsync()).Adapt<List<DefecthandleDetailModel>>();

        if (data.Type.Equals("IQC"))
        {
            
            if (data.DetailList != null && data.DetailList.Count > 0)
            {
                foreach (var detail in data.DetailList)
                {
                    detail.itemDefectList = (await _repository.Context.Queryable<QmsBusiInspectionitemdefectEntity>().Where(x => x.InspectionItem == detail.InspectionItemId).ToListAsync()).Adapt<List<QmsBusiInspectionitemdefectInfoOutput>>();
                }
            }
            // 查询报警单对应检验批使用决策项
            var inspectionDecision = await _repository.Context.Queryable<QmsBusiInspectionEntity, QmsBusiInspectionitemdecisionEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.Code == b.Inspectionlot && a.InspectionlogCode == b.Code))
                .Where((a, b) => a.InspectionlogCode == data.InspectionLot)
                .Select((a, b) => new
                {
                    Id = b.Id,
                    Inspectionlot = a.Code, // 报检单号
                    Code = a.InspectionlogCode, // 检验批号
                    IncomingQty = a.IncomingQty == null ? 0 : a.IncomingQty, // 来料数量
                    DestructivenessQty = b.DestructivenessQty == null ? 0 : b.DestructivenessQty, // 破环性数量
                    ReceiveQty = b.ReceiveQty == null ? 0 : b.ReceiveQty, // 接收数量
                    RejectQty = b.RejectQty == null ? 0 : b.RejectQty, // 拒收数量
                    DecisionDesc = b.DecisionDesc, // 使用决策备注
                }).ToListAsync();

            data.inspection = inspectionDecision;
        } 
        else if (data.Type.Equals("IPQC")){

            if (data.DetailList != null && data.DetailList.Count > 0)
            {
                foreach (var detail in data.DetailList)
                {
                    detail.itemDefectList = (await _repository.Context.Queryable<QmsBusiIpqcinspectionitemdefectEntity>().Where(x => x.InspectionItem == detail.InspectionItemId).ToListAsync()).Adapt<List<QmsBusiIpqcinspectionitemdefectInfoOutput>>();
                }
            }

        }

        
        return data;
    }

    #endregion

    #region POST

    /// <summary>
    /// 更新.
    /// </summary>
    /// <param name="input">请求参数</param>
    /// <returns></returns>
    [HttpPut("")]
    public async Task Update([FromBody] QmsBusiDefecthandleCrInput input)
    {
        var defecthandleEntity = input.Adapt<QmsBusiDefecthandleEntity>();
        var decision = input.inspection.ToObject<List<QmsBusiInspectionitemdecisionEntity>>();

        await _repository.Context.Updateable(defecthandleEntity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();

        if (!decision.IsNullOrEmpty())
        {
            await InspectionitemdecisionSubmit(decision);
        }

        // 状态为6 表明直接提交确认不合格品信息，无需调用工作流
        if (6.Equals(input.status))
        {
            // 修改检验批状态为已过帐，检验批使用决策更新
            if (input.type.Equals("IQC"))
            {
                await _repository.Context.Updateable<QmsBusiInspectionlotEntity>().
           SetColumns(it => new QmsBusiInspectionlotEntity() { Decision = input.decision, Status = 3, DecisionName = input.decisionName, LastModifyTime = DateTime.Now, LastModifyUserId = _userManager.UserId })
           .Where(it => it.Code == input.inspectionLot).ExecuteCommandAsync();
            }
            else if (input.type.Equals("IPQC")) {

                await _repository.Context.Updateable<QmsBusiIpqcinspectionlotEntity>().
          SetColumns(it => new QmsBusiIpqcinspectionlotEntity() { Decision = input.decision, Status = 3, DecisionName = input.decisionName, LastModifyTime = DateTime.Now, LastModifyUserId = _userManager.UserId })
          .Where(it => it.Code == input.inspectionLot).ExecuteCommandAsync();

            }
           
        }

        if (0.Equals(input.status))
        {
            var flowEngineEntity = await _repository.Context.Queryable<FlowEngineEntity>().FirstAsync(a => a.EnCode == "defecthandle" && a.EnabledMark == 1 && a.DeleteMark == null);
            if (flowEngineEntity == null) throw Oops.Oh(ErrorCode.COM1007);

            await FlowSubmit(defecthandleEntity.Id, flowEngineEntity);
        }
    }

    /// <summary>
    /// 不合格处理单审批完成更新检验批使用决策.
    /// </summary>
    /// <param name="input">参数</param>
    /// <returns></returns>
    [HttpPost("InspectionLot")]
    public async Task Update([FromBody] DefecthandleQuery input)
    { 
        if(string.IsNullOrEmpty(input.taskId)) throw Oops.Oh(ErrorCode.D1012);

        var data = await _repository.Context.Queryable<QmsBusiDefecthandleEntity,FlowTaskEntity>((a, b) => new JoinQueryInfos(JoinType.Left,a.Id == b.Id))
            .Where((a, b) => b.Id == input.taskId && a.DeleteMark == null)
            .Select(a => a).FirstAsync();

        if (data.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.COM1007);

        if (data.Type.Equals("IQC"))
        {
            var isOk = await _repository.Context.Updateable<QmsBusiInspectionlotEntity>().
           SetColumns(it => new QmsBusiInspectionlotEntity() { Decision = data.Decision, Status = 3, DecisionName = data.DecisionName, LastModifyTime = DateTime.Now, LastModifyUserId = _userManager.UserId })
           .Where(it => it.Code == data.InspectionLot).ExecuteCommandHasChangeAsync();
            if (!isOk)
                throw Oops.Oh(ErrorCode.COM1001);
        }
        else if (data.Type.Equals("IPQC"))
        {
            var isOk = await _repository.Context.Updateable<QmsBusiIpqcinspectionlotEntity>().
          SetColumns(it => new QmsBusiIpqcinspectionlotEntity() { Decision = data.Decision, Status = 3, DecisionName = data.DecisionName, LastModifyTime = DateTime.Now, LastModifyUserId = _userManager.UserId })
          .Where(it => it.Code == data.InspectionLot).ExecuteCommandHasChangeAsync();
            if (!isOk)
                throw Oops.Oh(ErrorCode.COM1001);
        }
    }

    #endregion

    #region PrivateMethod

    /// <summary>
    /// 新增使用决策信息.
    /// </summary>
    /// <param name="inputList">使用决策信息</param>
    /// <returns></returns>
    private async Task InspectionitemdecisionSubmit(List<QmsBusiInspectionitemdecisionEntity> inputList)
    {
        try
        {
            List<string> _idList = inputList.Where(w => !string.IsNullOrEmpty(w.Id)).Select(a => a.Id).ToList();

            _tenant.BeginTran();
            if (_idList != null && _idList.Count > 0)
            {
                await _repository.Context.Deleteable<QmsBusiInspectionitemdecisionEntity>()
                    .Where(w => _idList.Contains(w.Id)).ExecuteCommandAsync();
            }

           await _repository.Context.Insertable(inputList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();

            _tenant.CommitTran();
        }
        catch (Exception)
        {
            _tenant.RollbackTran();
            throw;
        }
    }


    /// <summary>
    /// 提交审核.
    /// </summary>
    /// <param name="id">主键值</param>
    /// <param name="flowEngineEntity">流程信息</param>
    /// <returns></returns>
    private async Task FlowSubmit(string id, FlowEngineEntity flowEngineEntity)
    {
        try
        {
            _tenant.BeginTran();

            var _entity = await _repository.FirstOrDefaultAsync(x => x.Id == id && x.DeleteMark == null);

            #region 业务信息
            _entity.Status = FlowTaskStatusEnum.Handle.ParseToInt();
            _entity.LastModifyTime = DateTime.Now;
            _entity.LastModifyUserId = _userManager.UserId;
            await _repository.UpdateAsync(_entity);
            #endregion

            #region 流程信息
            var flowTaskEntity = await _flowTaskRepository.GetTaskInfo(id);
            if (flowTaskEntity.IsNullOrEmpty())
            {
                await _flowTaskManager.Submit(string.Empty, flowEngineEntity.Id, id, _userManager.User.RealName + "的不合格品处理单", 1, _entity.Code, _entity.Adapt<DefecthandleInfoOutput>(), 0);
            }
            else 
            {
                await _flowTaskManager.Submit(id, flowEngineEntity.Id, id, _userManager.User.RealName + "的不合格品处理单", 1, _entity.Code, _entity.Adapt<DefecthandleInfoOutput>(), 0);
            }
            #endregion
            _tenant.CommitTran();
        }
        catch (Exception)
        {
            _tenant.RollbackTran();
            throw;
        }
    }
    #endregion
}